﻿#define ConsoleLog
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace MaJiang{
	public class MJ_DaskLog{
		StringBuilder buffer = new StringBuilder();
		string _log;
		public string log{
			get{
				return _log;
			}
		}
		public void AddLog(string __log){
			buffer.Append (__log);
			buffer.Append ("\n");
			_log = buffer.ToString ();
		}
		public void Clear(){
			buffer = new StringBuilder ();
			_log = "";
		}

	}

	#region BaseCommand
	public class MJ_CommandMgr{
		List<MJ_Command> commands = new List<MJ_Command>();
		CardManager cardMgr;
		public MJ_CommandMgr(CardManager _cardMgr){
			cardMgr = _cardMgr;
		}
		MJ_Command currentCmd{
			get{
				if (commands.Count > 0)
					return commands [0];
				return null;
			}
		}
		public string getCurrentCMDName(){
			return currentCmd == null ? "无命令" : currentCmd.CMDName;
		}
		public void DoCommand(){
			if (currentCmd != null)
				currentCmd.Do ();
		}

		public T AddCommand<T>()where T:MJ_Command,new(){
			T t = new T ();
			AddCommand (t);
			return t;
		}
		public void ClearCommand(){
			commands.Clear ();
		}
		public void AddCommand(MJ_Command command,bool autoDo = false){
			command.Rest ();
			command.SetMgr (cardMgr);
			if(autoDo)
				command.Do ();
			if(!command.isFinish)
				commands.Add (command);
		}

		public void Update(float dt){
			if (currentCmd != null) {
				currentCmd.Update (dt);
				if (currentCmd.isFinish)
					commands.Remove (currentCmd);
			}
		}
	}

	public class MJ_Command{
		bool _isfinish;
		StringBuilder buffer = new StringBuilder();
		string _cmdName = "";
		public const string NoCommandName = "无命令";
		public bool isFinish{
			get{
				return _isfinish;
			}
		}
		protected virtual string cmdName{
			get{
				return NoCommandName;
			}
		}

		public string CMDName{
			get{
				return _cmdName == ""?cmdName:_cmdName;
			}
			set{
				_cmdName = value;
			}
		}
		protected CardManager cardMgr;
		public float life;
		public void SetMgr(CardManager _mgr){
			cardMgr = _mgr;
		}
		public virtual void FinishNow(){
			_isfinish = true;
			if (log != "")
				cardMgr.logMgr.AddLog (log);
		}
		public virtual void Do(){

		}
		public virtual void Update(float dt){
			life += dt;
		}
		protected void AddLog(string _log){
			buffer.Append (_log);
			#if ConsoleLog && UNITY_EDITOR
			Debug.Log(_log);
			#endif
		}
		public string log{
			get{
				return buffer.ToString ();
			}
		}
		public virtual void Rest(){
			_isfinish = false;
			life = 0;
		}
	}

	public class MJ_DelegateCommand:MJ_Command{
		public System.Action<MJ_DelegateCommand> onFinish;
		public System.Action<MJ_DelegateCommand> onDo;
		public System.Action<MJ_DelegateCommand,float> onUpdate;
		public override void Do ()
		{
			base.Do ();
			if (onDo != null)
				onDo (this);
		}
		public override void FinishNow ()
		{
			base.FinishNow ();
			if (onFinish != null)
				onFinish (this);
		}
		public override void Update (float dt)
		{
			base.Update (dt);
			if (onUpdate != null)
				onUpdate (this, dt);
		}
	}

	public class MJ_CommandOnlyOne:MJ_Command{
		
		public override void Do ()
		{
			base.Do ();
			FinishNow ();
		}
	}

	public class MJ_CommandGroup:MJ_Command{
		protected List<MJ_Command> cmds = new List<MJ_Command> ();
		protected bool isRuning;
		/// <summary>
		/// 是否需要停下来等待万家输入
		/// </summary>
		public bool needPauseCMD = false;
		protected void AddPauseCMD(){
			if(needPauseCMD)
				AddCommand<PauseCommand> ();
		}
		public T AddCommand<T>()where T:MJ_Command,new(){
			T t = new T ();
			AddCommand (t);
			return t;
		}
		public void AddCommand(MJ_Command cmd){
			cmds.Add (cmd);
		}
		public MJ_Command currentCommand{
			get{ 
				if (cmds.Count > 0)
					return cmds [0];
				return null;
			}
		}
		public MJ_Command nextCommand{
			get{ 
				if (cmds.Count > 1)
					return cmds [1];
				return null;
			}
		}
		public MJ_CommandGroup(){
			ReadyCommand ();
		}
		public override void Rest ()
		{
			base.Rest ();
			ReadyCommand();
		}
		protected virtual void ReadyCommand(){
			
		}
		public override void Do ()
		{
			isRuning = true;
			base.Do ();
		}
		public MJ_CommandGroup(bool _needPause){
			needPauseCMD = _needPause;
		}
	}
	public class PauseCommand:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "等待";
			}
		}
	}
	#endregion

	#region Command
	/// <summary>
	/// 默认洗牌
	/// </summary>
	public class CMD_Shuffle:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "洗牌";
			}
		}
		public override void Do ()
		{
			//默认洗牌
			cardMgr.DefaultShuffle ();
			#if ConsoleLog
			AddLog ("------------洗牌完毕----------");
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 洗牌完毕
	/// </summary>
	public class CMD_ShuffleFinish:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "洗牌完毕";
			}
		}
		public override void Do ()
		{
			base.Do ();
			cardMgr.touchPlayerIndex = cardMgr.banker.index;
		}
	}

	/// <summary>
	/// 抽选庄家
	/// </summary>
	public class ChooseBanker:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "选庄";
			}
		}
		public override void Do ()
		{
			if (cardMgr.isFirstGame) {
				cardMgr.SetBanker (Random.Range (0, 4));
				#if ConsoleLog
				AddLog ("----庄家是:" + (cardMgr.banker.index + 1) + "号玩家");
				#endif
			} else {
				#if ConsoleLog
				Debug.Log ("当前盘数:" + cardMgr.turnCount);
				#endif
			}
			base.Do ();
		}
	}

	/// <summary>
	/// 选择第一个摸牌的
	/// </summary>
	public class ChooseFirstTouch:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "选摸牌人";
			}
		}
		public override void Do ()
		{
			
			cardMgr.touchPlayerIndex = Random.Range (0, 4);
			#if ConsoleLog
			AddLog ("----摸牌人:" + (cardMgr.touchPlayerIndex + 1) + "号玩家");
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 选择起手摸排循序
	/// </summary>
	public class ChooseFirstCardIndex:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "选摸牌顺序";
			}
		}
		public override void Do ()
		{
			cardMgr.firstRandomCardIndex = new int[2];
			cardMgr.firstRandomCardIndex [0] = Random.Range (1, 7);
			cardMgr.firstRandomCardIndex [1] = Random.Range (1, 7);
			var playerrightid = (cardMgr.touchPlayerIndex * 36) - 1;
			var randomvalue = cardMgr.firstRandomCardIndex [0] + cardMgr.firstRandomCardIndex [1];
			var random = playerrightid - randomvalue;
			cardMgr.nextCardId = random + 1;
			cardMgr.backCardId = random;
			#if ConsoleLog
			AddLog ("----骰子点数[" + cardMgr.firstRandomCardIndex [0] + "," + cardMgr.firstRandomCardIndex [1] + "],从" + (cardMgr.touchPlayerIndex + 1) + "号玩家右手边开始数第" + randomvalue + "张开始摸排");
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 起手摸牌
	/// </summary>
	public class PlayerFirstTouchCard:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "起手摸牌";
			}
		}		
		public override void Do ()
		{
			
			var onecount = 4;
			var turncount = 4;
			for (var i = 0; i < turncount; i++) {
				for (var p = 0; p < cardMgr.players.Length; p++) {
					var player = cardMgr.players [p];
					for (var o = 0; o < onecount; o++) {
						player.TouchCard (cardMgr.TouchNextCard());
					}
				}
			}
			#if ConsoleLog
			var _log = "摸牌结束\n";
			MaJiangTool.getPlayersCardsName(ref _log,cardMgr);
			#endif
			var bankerCard = cardMgr.TouchNextCard ();
			cardMgr.banker.TouchCard (bankerCard);

			#if ConsoleLog
			_log+= "庄家额外摸一张牌:"+bankerCard.CardName;
			AddLog (_log);
			#endif
			base.Do ();

		}
	}

	/// <summary>
	/// 补花
	/// </summary>
	public class PlayerFirstBuHua:MJ_CommandOnlyOne{
		enCradType[] huaTypes;
		public PlayerFirstBuHua(enCradType[] _huaTypes):base(){
			huaTypes = _huaTypes;
		}
		protected override string cmdName {
			get {
				return "补花";
			}
		}
		public override void Do ()
		{
			List<int> playerOrder = new List<int> ();
			var order = cardMgr.banker.index;
			#if ConsoleLog
			var _log = "----开始补花,庄家:"+cardMgr.banker.indexName+"\n";
			#endif

			for (var i = 0; i < 4; i++) {
				playerOrder.Add (order);
				cardMgr.NextPlayerIndex (ref order);
			}


			while (playerOrder.Count > 0) {
				for (var i = 0; i < playerOrder.Count; i++) {
					int currentOrderId = playerOrder [i];
					var player = cardMgr.players [currentOrderId];
					var hua = player.getCardsByTypes(huaTypes);	
					int huaCount = hua.Count;
					player.DisHuaCards (hua);
					var newCards = new List<Card> ();
					for(var h = 0;h<hua.Count;h++){
						newCards.Add(cardMgr.TouchBackCard ());
					}
					player.AddCards (newCards);

					#if ConsoleLog
					if(huaCount == 0){
						_log += (currentOrderId+1)+"号玩家没有花:\n";
						MaJiangTool.getPlayerCardsName(ref _log,(currentOrderId),player);
					}
					else
					{
						_log+= (currentOrderId+1)+"号玩家的花牌:";
						for(var c = 0;c < hua.Count;c++){
							_log+= hua[c].CardName;
						}
						_log+= "换成了:";
						for(var c = 0;c < newCards.Count;c++){
							_log+= newCards[c].CardName;
						}
						_log += "\n";
					}
					#endif

					if (huaCount == 0) {
						playerOrder.RemoveAt (i);
						i--;
					}
				}
			}

			#if ConsoleLog
			_log += "----补花完毕\n";
			MaJiangTool.getPlayersCardsName(ref _log,cardMgr);
			AddLog(_log);
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 开金
	/// </summary>
	public class FindWildCard:MJ_CommandOnlyOne{
		/// <summary>
		/// 可以作为金的牌
		/// </summary>
		enCradType[] canBeWildCard;
		public FindWildCard(enCradType[] _canBeWildCard):base(){
			canBeWildCard = _canBeWildCard;
		}
		protected override string cmdName {
			get {
				return "开金";
			}
		}
		public override void Do ()
		{
			var find = false;
			#if ConsoleLog
			var _log = "----开始开金\n";
			#endif
			while (!find) {
				var wildCard = cardMgr.TouchBackCard ();

				if (wildCard.isLikeTypes (canBeWildCard)) {
					find = true;
					cardMgr.wildCard = wildCard;
					#if ConsoleLog
					_log += "!金:"+wildCard.CardName;
					#endif
				} else {
					cardMgr.banker.AddHuaCard (wildCard);
					#if ConsoleLog
					_log += "摸出了一张:"+wildCard.CardName+"庄家笑纳了\n";
					#endif
				}
			}
			#if ConsoleLog
			AddLog(_log);
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 整牌
	/// </summary>
	public class SortPlayersCard:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "牌面整理";
			}
		}
		public override void Do ()
		{
			#if ConsoleLog
			var _log = "----开始整理牌面\n";
			#endif
			for (var i = 0; i < cardMgr.players.Length; i++) {
				cardMgr.players [i].SortCards ();
				#if ConsoleLog
				MaJiangTool.getPlayerCardsName(ref _log,i,cardMgr.players[i]);
				#endif
			}
			#if ConsoleLog
			AddLog(_log);
			#endif
			base.Do ();
		}
	}

	/// <summary>
	/// 摸牌
	/// </summary>
	public class TouchCard:MJ_CommandOnlyOne{
	}

	/// <summary>
	/// 检查天胡
	/// </summary>
	public class Check_TianHu:MJ_CommandOnlyOne{
		protected override string cmdName {
			get {
				return "检查天胡";
			}
		}
		public override void Do ()
		{
			
			var canhu = cardMgr.IsCanHuByPlayer (cardMgr.banker);
			Debug.Log ("天胡:"+canhu);
			base.Do ();
		}
	}
	#endregion

	#region CommandGroup
	/// <summary>
	/// 福州麻将洗牌
	/// </summary>
	public class CMDG_XIPAI_FUZHOU:MJ_CommandGroup{
		public CMDG_XIPAI_FUZHOU(bool _needPause):base(_needPause){
		}
		protected override string cmdName {
			get {
				return  (nextCommand != null) ?nextCommand.CMDName: "开始游戏";
			}
		}
		protected override void ReadyCommand ()
		{
			AddCommand<CMD_Shuffle> ();
			AddCommand<ChooseBanker> ();
			AddPauseCMD ();
			AddCommand<ChooseFirstTouch> ();
			AddPauseCMD ();
			AddCommand<ChooseFirstCardIndex> ();
			AddCommand<PlayerFirstTouchCard> ();
			AddCommand(new PlayerFirstBuHua(new enCradType[]{enCradType.Feng,enCradType.Hua,enCradType.Jian}));
			AddPauseCMD ();
			AddCommand(new FindWildCard(new enCradType[]{enCradType.Wan,enCradType.Tiao,enCradType.Bing}));
			AddCommand<SortPlayersCard> ();
			AddCommand<CMD_ShuffleFinish> ();
			AddCommand<Check_TianHu> ();
			base.ReadyCommand ();
		}
		public override void Do ()
		{
			if (cmds.Count == 0) {
				FinishNow ();
			}else{
				while (cmds.Count > 0) {
					if (cmds [0] is PauseCommand) {
						cmds.RemoveAt (0);
					} else {
						break;
					}
				}
				while (cmds.Count > 0) {
					if (cmds [0] is PauseCommand) {
						return;
					}
					else {
						cardMgr.DoCommand (cmds [0]);
						cmds.RemoveAt (0);
					}
				}
				FinishNow ();
			}
			base.Do ();
		}
	}
	#endregion

	#region 玩法
	/// <summary>
	/// 玩法
	/// </summary>
	public class CMD_WANFA:MJ_Command{
		public override void Do ()
		{
			
			Debug.Log ("设置玩法:");
			SetConf ();
			SetWanFaAndXiPai ();
			FinishNow ();
			base.Do ();
		}
		protected virtual void SetConf(){
		}
		protected virtual void SetWanFaAndXiPai(){
		}
	}
	public class CMD_WANFA_FUZHOU:CMD_WANFA{
		protected override string cmdName {
			get {
				return "福州麻将";
			}
		}
		protected override void SetConf ()
		{
			base.SetConf ();
		}
		protected override void SetWanFaAndXiPai ()
		{
			base.SetWanFaAndXiPai ();
			cardMgr.SetHuPaiWanFa (new HUPAI_FUZHOU ());
			cardMgr.SetShuffle (new CMDG_XIPAI_FUZHOU (false));
		}
	}
	#endregion
}